package org.jrpc.server2;

import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import net.sf.cglib.reflect.FastClass;
import net.sf.cglib.reflect.FastMethod;
import org.jrpc.common.baen.RpcRequest;
import org.jrpc.common.baen.RpcResponse;
import org.jrpc.common.utils.StringUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Map;
import java.util.concurrent.ExecutorService;

/**
 * RPC 服务端处理器（用于处理 RPC 请求）
 *
 * @since 1.0.0
 */
public class RpcServerHandler extends SimpleChannelInboundHandler<RpcRequest> {

    private static final Logger LOGGER = LoggerFactory.getLogger(RpcServerHandler.class);

    private final Map<String, Object> handlerMap;

    private ExecutorService executorService=JRpcExecutors.newFixedThreadPool(8,100);

    public RpcServerHandler(Map<String, Object> handlerMap) {
        this.handlerMap = handlerMap;
    }

    private ChannelHandlerContext ctx;

    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        this.ctx = ctx;
        System.err.println("有客户端连接："+ctx.channel().remoteAddress().toString());
    }

    @Override
    public void channelRead0(ChannelHandlerContext ctx, RpcRequest request) throws Exception {
        // 创建并初始化 RPC 响应对象
        /*RpcResponse response = new RpcResponse();
        response.setRequestId(request.getRequestId());
        try {
            LOGGER.info("requestId:"+request.getRequestId());
            Object result = handle(request);
            response.setResult(result);
        } catch (Exception e) {
            LOGGER.error("handle result failure", e);
            response.setException(e);
        }
        // 写入 RPC 响应对象并自动关闭连接
        ctx.writeAndFlush(response);*/
        try {
            executorService.submit(new Tasks(ctx,request));
        }catch (Exception e){
            e.printStackTrace();
        }

    }

    private class Tasks implements Runnable{
        private ChannelHandlerContext ctx;
        private RpcRequest request;
        public Tasks(ChannelHandlerContext ctx, RpcRequest request){
            this.ctx=ctx;
            this.request=request;
        }
        @Override
        public void run() {
            // 创建并初始化 RPC 响应对象
            RpcResponse response = new RpcResponse();
            response.setRequestId(request.getRequestId());
            try {
                LOGGER.info("requestId:"+request.getRequestId());
                Object result = handle(request);
                response.setResult(result);
            } catch (Exception e) {
                LOGGER.error("handle result failure", e);
                response.setException(e);
            }
            // 写入 RPC 响应对象并自动关闭连接
            ctx.writeAndFlush(response);
        }
    }
    private Object handle(RpcRequest request) throws Exception {
        // 获取服务对象
        String serviceName = request.getInterfaceName();
        String serviceVersion = request.getServiceVersion();
        if (StringUtil.isNotEmpty(serviceVersion)) {
            serviceName += "-" + serviceVersion;
        }
        Object serviceBean = handlerMap.get(serviceName);
        if (serviceBean == null) {
            throw new RuntimeException(String.format("can not find service bean by key: %s", serviceName));
        }
        // 获取反射调用所需的参数
        Class<?> serviceClass = serviceBean.getClass();
        String methodName = request.getMethodName();
        Class<?>[] parameterTypes = request.getParameterTypes();
        Object[] parameters = request.getParameters();
        // 执行反射调用
//        Method method = serviceClass.getMethod(methodName, parameterTypes);
//        method.setAccessible(true);
//        return method.invoke(serviceBean, parameters);
        // 使用 CGLib 执行反射调用
        FastClass serviceFastClass = FastClass.create(serviceClass);
        FastMethod serviceFastMethod = serviceFastClass.getMethod(methodName, parameterTypes);
        return serviceFastMethod.invoke(serviceBean, parameters);
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
        LOGGER.error("server caught exception", cause);
        ctx.channel().close();
        ctx.close();
    }

    @Override
    public void handlerRemoved(ChannelHandlerContext ctx) throws Exception {

        //这里执行客户端断开连接后的操作
        System.out.println("==================");
        System.out.println(ctx);
        ctx.channel().close();
        ctx.close();
    }
}
